package com.demo.hdz.getbluetoothmac;

import android.app.Activity;
import android.bluetooth.BluetoothA2dp;
import android.bluetooth.BluetoothAdapter;
import android.bluetooth.BluetoothClass;
import android.bluetooth.BluetoothDevice;
import android.bluetooth.BluetoothProfile;
import android.content.BroadcastReceiver;
import android.content.Context;
import android.content.Intent;
import android.content.IntentFilter;
import android.media.AudioManager;
import android.media.MediaPlayer;
import android.net.Uri;
import android.os.Build;
import android.os.Bundle;
import android.util.Log;
import android.widget.TextView;

import java.lang.reflect.Field;
import java.lang.reflect.Method;
import java.util.List;
import java.util.Set;

/**
 * @author hdz
 */
public class MainActivity extends Activity {

    private TextView mTvLocalBluetoothMAC;
    private TextView mTvLocalBluetoothName;
    private TextView mTvRemoteBluetoothMAC;
    private TextView mTvRemoteBluetoothName;

    private static final String TAG = "BluetoothA2DPTest";
    private BroadcastReceiver mBroadcastReceiver;
    private BluetoothA2dp mBluetoothA2dp;
    private BluetoothAdapter mBluetoothAdapter;
    private final String DEVICE_NAME = "Solo V4.1";
    private BluetoothDevice mBluetoothDevice;
    private MediaPlayer mMediaPlayer;

    @Override
    protected void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
        setContentView(R.layout.activity_main);

        TextView tvAppVer = (TextView) findViewById(R.id.tvAppVer);
        tvAppVer.setText(BuildConfig.APP_VERSION);

        TextView tvDevMode = (TextView) findViewById(R.id.tvDevMode);
        tvDevMode.setText(android.os.Build.MODEL);

        TextView tvAndroidVer = (TextView) findViewById(R.id.tvAndroidVer);
        tvAndroidVer.setText(android.os.Build.VERSION.RELEASE);

        TextView tvVer = (TextView) findViewById(R.id.tvAPIVer);
        tvVer.setText(""+Build.VERSION.SDK_INT);
        //tvVer.setText(android.os.Build.VERSION.SDK);

        mTvLocalBluetoothName = (TextView) findViewById(R.id.tvBluetoothName);
        mTvLocalBluetoothMAC = (TextView) findViewById(R.id.tvBluetoothMac);
        mTvRemoteBluetoothName = (TextView) findViewById(R.id.tvRemoteBluetoothName);
        mTvRemoteBluetoothMAC = (TextView) findViewById(R.id.tvRemoteBluetoothMac);

        initParameters();
    }


    //https://langw.gitbooks.io/blesummary-/content/24_android_bu_tong_lan_ya_ban_ben_huo_qu_lan_ya_di.html
    public String getLocalBluetoothMAC() {
        BluetoothAdapter btAdapter = BluetoothAdapter.getDefaultAdapter();
        if (btAdapter == null) {
            return "";
        }

        mTvLocalBluetoothName.setText(btAdapter.getName());

        String bluetoothMAC = "";
        if (Build.VERSION.SDK_INT < 23) {
            bluetoothMAC = btAdapter.getAddress();
        } else {
            Class<? extends BluetoothAdapter> btAdapterClass = btAdapter.getClass();
            try {
                Class<?> btClass = Class.forName("android.bluetooth.IBluetooth");
                Field bluetooth = btAdapterClass.getDeclaredField("mService");
                bluetooth.setAccessible(true);
                Method btAddress = btClass.getMethod("getAddress");
                btAddress.setAccessible(true);
                bluetoothMAC = (String) btAddress.invoke(bluetooth.get(btAdapter));
            } catch (Exception e) {
                bluetoothMAC = btAdapter.getAddress();
            }
        }

        if (bluetoothMAC.equals("02:00:00:00:00:00")) {
            return "";
        } else {
            return bluetoothMAC;
        }
    }

//http://blog.csdn.net/lang523493505/article/details/53149726
//http://blog.csdn.net/jasonwang18/article/details/61214431
//http://www.cnblogs.com/Free-Thinker/p/6763635.html
    //只能连接蓝牙耳机等多媒体设备
    private void getConnectedBluetoothMAC(final Context context) {
        BluetoothAdapter btAdapter = BluetoothAdapter.getDefaultAdapter();
        if (btAdapter == null) {
            return;
        }
        int a2dp = btAdapter.getProfileConnectionState(BluetoothProfile.A2DP);
        int headset = btAdapter.getProfileConnectionState(BluetoothProfile.HEADSET);
        int health = btAdapter.getProfileConnectionState(BluetoothProfile.HEALTH);
        int flag = -1;
        if (a2dp == BluetoothProfile.STATE_CONNECTED) {
            flag = a2dp;
        } else if (headset == BluetoothProfile.STATE_CONNECTED) {
            flag = headset;
        } else if (health == BluetoothProfile.STATE_CONNECTED) {
            flag = health;
        }
        if (flag != -1) {
            btAdapter.getProfileProxy(context, new BluetoothProfile.ServiceListener() {
                @Override
                public void onServiceDisconnected(int profile) {

                }
                @Override
                public void onServiceConnected(int profile, BluetoothProfile proxy) {
                    List<BluetoothDevice> mDevices = proxy.getConnectedDevices();
                    if (mDevices != null && mDevices.size() > 0) {
                        mTvRemoteBluetoothMAC.setText( mDevices.get(0).getAddress() );
                        mTvRemoteBluetoothName.setText( mDevices.get(0).getName() );
                    }
                    mBluetoothA2dp = (BluetoothA2dp)proxy;
                }
            }, flag);
        } else {
            mTvRemoteBluetoothMAC.setText( getString(R.string.bluetoothNotConnect) );
            mTvRemoteBluetoothName.setText( getString(R.string.bluetoothNotConnect) );
        }
    }

    @Override
    protected void onResume() {
        super.onResume();

        //String macAddress = android.provider.Settings.Secure.getString(getContentResolver(),"bluetooth_address");
        String localBluetoothMAC = getLocalBluetoothMAC();
        if (localBluetoothMAC.equals("")) {
            mTvLocalBluetoothMAC.setText(getString(R.string.bluetoothNotOpen));
        } else {
            mTvLocalBluetoothMAC.setText(localBluetoothMAC);
        }

        String remoteBluetoothMAC = getRemoteBluetoothMAC();
        if (!remoteBluetoothMAC.equals("")) {
            mTvRemoteBluetoothMAC.setText(remoteBluetoothMAC);
        } else {
            getConnectedBluetoothMAC(this);
        }
    }


    //只能获取手机连接的蓝牙MAC
    private String getRemoteBluetoothMAC() {
        BluetoothAdapter adapter = BluetoothAdapter.getDefaultAdapter();
        mBluetoothAdapter = adapter;
        Class<BluetoothAdapter> bluetoothAdapterClass = BluetoothAdapter.class;
        try {
            Method method = bluetoothAdapterClass.getDeclaredMethod("getConnectionState", (Class[]) null);
            method.setAccessible(true);
            int state = (int) method.invoke(adapter, (Object[]) null);
            if(state == BluetoothAdapter.STATE_CONNECTED){
                Set<BluetoothDevice> devices = adapter.getBondedDevices();
                for(BluetoothDevice device : devices){
                    Method isConnectedMethod = BluetoothDevice.class.getDeclaredMethod("isConnected", (Class[]) null);
                    method.setAccessible(true);
                    boolean isConnected = (boolean) isConnectedMethod.invoke(device, (Object[]) null);
                    if(isConnected){
                        startPlay();
                        mBluetoothDevice = device;
                        mTvRemoteBluetoothName.setText(device.getName());
                        return device.getAddress();
                    }
                }
            }

        } catch (Exception e) {
            e.printStackTrace();
        }
        return "";
    }

    @Override
    protected void onStop() {
        super.onStop();
        //disconnect();
        removeAllBonds();
        //disconnect();
        //disableAdapter();
        //stopPlay();
        startDiscovery();
    }

    @Override
    protected void onDestroy() {
        stopPlay();
        unregisterReceiver(mBroadcastReceiver);
        super.onDestroy();
    }

    private void initParameters(){
        mBluetoothAdapter = BluetoothAdapter.getDefaultAdapter();
        if(mBluetoothAdapter == null){
            Log.e(TAG,"have no bluetooth adapter.");
            return;
        }

        /*
        // 如果蓝牙已经打开就关闭
        if(mBluetoothAdapter.isEnabled()){
            mBluetoothAdapter.disable();
            return;
        }
        */
        if(!mBluetoothAdapter.isEnabled()){
            mBluetoothAdapter.enable();
        }else{
            //开始搜索附近蓝牙
            startDiscovery();
            //绑定BluetoothA2DP，获得service
            getBluetoothA2DP();
        }

        //监听广播
        mBroadcastReceiver = new BroadcastReceiver() {
            @Override
            public void onReceive(Context context, Intent intent) {
                BluetoothDevice device;
                Log.d(TAG, "initParameters: "+intent.getAction());
                switch (intent.getAction()) {
                    case BluetoothA2dp.ACTION_CONNECTION_STATE_CHANGED:
                        device = intent.getParcelableExtra(BluetoothDevice.EXTRA_DEVICE);
                        onConnectionStateChanged(intent.getIntExtra(BluetoothA2dp.EXTRA_STATE, -1), device);
                        break;
                    case BluetoothA2dp.ACTION_PLAYING_STATE_CHANGED:
                        int state = intent.getIntExtra(BluetoothA2dp.EXTRA_STATE, -1);
                        onPlayingStateChanged(state);
                        break;
                    case BluetoothDevice.ACTION_FOUND:
                        device = intent.getParcelableExtra(BluetoothDevice.EXTRA_DEVICE);
                        Log.i(TAG, "Found device:" + device.getName());
                        int deviceClassType = device.getBluetoothClass().getDeviceClass();
                        //找到指定的蓝牙设备
                        if (deviceClassType == BluetoothClass.Device.AUDIO_VIDEO_WEARABLE_HEADSET || deviceClassType == BluetoothClass.Device.AUDIO_VIDEO_HEADPHONES) {
                            if (device.getName().equals(DEVICE_NAME)) {
                                Log.i(TAG, "Found device:" + device.getName());
                                mBluetoothDevice = device;
                                //start bond，开始配对
                                createBond();
                            }
                        }
                        break;
                    case BluetoothDevice.ACTION_BOND_STATE_CHANGED:
                        int bondState = intent.getIntExtra(BluetoothDevice.EXTRA_BOND_STATE,BluetoothDevice.BOND_NONE);
                        device = intent.getParcelableExtra(BluetoothDevice.EXTRA_DEVICE);
                        onBondStateChanged(bondState, device);
                        break;
                    case BluetoothAdapter.ACTION_STATE_CHANGED:
                        state = intent.getIntExtra(BluetoothAdapter.EXTRA_STATE, -1);
                        onStateChanged(state);
                        break;
                    default:
                        break;
                }
            }
        };
        IntentFilter filter = new IntentFilter();
        filter.addAction(BluetoothA2dp.ACTION_CONNECTION_STATE_CHANGED);
        filter.addAction(BluetoothA2dp.ACTION_PLAYING_STATE_CHANGED);
        filter.addAction(BluetoothDevice.ACTION_FOUND);
        filter.addAction(BluetoothDevice.ACTION_BOND_STATE_CHANGED);
        filter.addAction(BluetoothAdapter.ACTION_STATE_CHANGED);
        registerReceiver(mBroadcastReceiver, filter);
    }

    private void onConnectionStateChanged(int state, BluetoothDevice device) {
        switch (state) {
            case BluetoothA2dp.STATE_CONNECTING:
                Log.i(TAG, "onConnectionStateChanged: device " + device.getName() +" connecting");
                break;
            case BluetoothA2dp.STATE_CONNECTED:
                Log.i(TAG, "onConnectionStateChanged: device " + device.getName() +" connected");
                //连接成功，开始播放
                startPlay();
                break;
            case BluetoothA2dp.STATE_DISCONNECTING:
                Log.i(TAG, "onConnectionStateChanged: device " + device.getName() +" disconnecting");
                break;
            case BluetoothA2dp.STATE_DISCONNECTED:
                Log.i(TAG, "onConnectionStateChanged: device " + device.getName() +" disconnected");
                break;
            default:
                Log.i(TAG, "onConnectionStateChanged: Unknown " + state);
                break;
        }
    }
    private void onPlayingStateChanged(int state) {
        switch (state) {
            case BluetoothA2dp.STATE_PLAYING:
                Log.i(TAG, "onPlayingStateChanged: playing.");
                break;
            case BluetoothA2dp.STATE_NOT_PLAYING:
                Log.i(TAG, "onPlayingStateChanged: not playing");
                break;
            default:
                Log.i(TAG, "onPlayingStateChanged: Unknown " + state);
                break;
        }
    }
    private void onBondStateChanged(int state, BluetoothDevice device) {
        switch (state){
            case BluetoothDevice.BOND_BONDED:
                //配对成功
                Log.i(TAG, "onBondStateChanged: Device "+device.getName()+" bonded.");
                mBluetoothAdapter.cancelDiscovery();  //取消搜索
                connect();  //连接蓝牙设备
                break;
            case BluetoothDevice.BOND_BONDING:
                Log.i(TAG, "onBondStateChanged: Device "+device.getName()+" bonding.");
                break;
            case BluetoothDevice.BOND_NONE:
                Log.i(TAG, "onBondStateChanged: Device "+device.getName()+" not bonded.");
                //不知道是蓝牙耳机的关系还是什么原因，经常配对不成功
                //配对不成功的话，重新尝试配对
                mBluetoothDevice = device;
                createBond();
                break;
            default:
                Log.i(TAG, "onBondStateChanged: Unknown " + state);
                break;
        }
    }
    private void onStateChanged(int state) {
        switch (state) {
            case BluetoothAdapter.STATE_TURNING_ON:
                Log.i(TAG, "onStateChanged: BluetoothAdapter is turning on.");
                break;
            case BluetoothAdapter.STATE_ON:
                Log.i(TAG, "onStateChanged: BluetoothAdapter is on.");
                //蓝牙已打开，开始搜索并连接service
                startDiscovery();
                getBluetoothA2DP();
                break;
            case BluetoothAdapter.STATE_TURNING_OFF:
                Log.i(TAG, "onStateChanged: BluetoothAdapter is turning off.");
                break;
            case BluetoothAdapter.STATE_OFF:
                Log.i(TAG, "onStateChanged: BluetoothAdapter is off.");
                break;
            default:
                Log.i(TAG, "onStateChanged: Unknown " + state);
                break;
        }
    }

    private void startDiscovery(){
        Log.i(TAG,"mBluetoothAdapter startDiscovery.");
        if(mBluetoothAdapter!=null && mBluetoothAdapter.isEnabled() && !mBluetoothAdapter.isDiscovering()){
            mBluetoothAdapter.startDiscovery();
        }
    }

    private void getBluetoothA2DP(){
        Log.i(TAG,"getBluetoothA2DP");
        if(mBluetoothAdapter == null){
            return;
        }

        if(mBluetoothA2dp != null){
            return;
        }

        mBluetoothAdapter.getProfileProxy(this, new BluetoothProfile.ServiceListener() {
            @Override
            public void onServiceConnected(int profile, BluetoothProfile proxy) {
                if(profile == BluetoothProfile.A2DP){
                    //Service连接成功，获得BluetoothA2DP
                    mBluetoothA2dp = (BluetoothA2dp)proxy;
                }
            }

            @Override
            public void onServiceDisconnected(int profile) {

            }
        },BluetoothProfile.A2DP);
    }

    private void createBond() {
        Log.i(TAG, "createBond");
        if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.KITKAT) {
            if (mBluetoothDevice != null) {
                mBluetoothDevice.createBond();
            }
        }
    }

    /**
     * connect和disconnect都是hide方法，普通应用只能通过反射机制来调用该方法
     */
    private void connect(){
        Log.i(TAG,"connect");
        if(mBluetoothA2dp == null){
            return;
        }
        if(mBluetoothDevice == null){
            return;
        }
        try {
            Method connect = mBluetoothA2dp.getClass().getDeclaredMethod("connect", BluetoothDevice.class);
            connect.setAccessible(true);
            connect.invoke(mBluetoothA2dp, mBluetoothDevice);
        } catch (Exception e) {
            Log.e(TAG,"connect exception:"+e);
            e.printStackTrace();
        }
    }
    private void disconnect(){
        Log.i(TAG,"disconnect");
        if(mBluetoothA2dp == null){
            return;
        }
        if(mBluetoothDevice == null){
            return;
        }
        try {
            Log.i(TAG,"disconnect 2");
            Method disconnect = mBluetoothA2dp.getClass().getDeclaredMethod("disconnect", BluetoothDevice.class);
            disconnect.setAccessible(true);
            disconnect.invoke(mBluetoothA2dp, mBluetoothDevice);
        } catch (Exception e) {
            Log.e(TAG,"connect exception:"+e);
            e.printStackTrace();
        }
    }

    /**
     * 开始播放音乐
     */
    private void startPlay(){
        Log.i(TAG, "startPlay");
        AudioManager mAudioManager= (AudioManager)getSystemService(AUDIO_SERVICE);
        if(mAudioManager!=null){
            int maxVolume = mAudioManager.getStreamMaxVolume(AudioManager.STREAM_MUSIC);
            mAudioManager.setStreamVolume(AudioManager.STREAM_MUSIC,maxVolume,0);
        }
        Uri uri = Uri.parse("android.resource://"+getPackageName()+"/"+ R.raw.test);
        mMediaPlayer = new MediaPlayer();
        mMediaPlayer.reset();
        try {
            mMediaPlayer.setDataSource(this,uri);
            mMediaPlayer.setOnCompletionListener(new MediaPlayer.OnCompletionListener() {
                @Override
                public void onCompletion(MediaPlayer mp) {
                    //播放完成，可以考虑断开连接
                    disconnect();
                }
            });
            mMediaPlayer.setOnErrorListener(new MediaPlayer.OnErrorListener() {
                @Override
                public boolean onError(MediaPlayer mp, int what, int extra) {
                    Log.e(TAG, "Playback error.");
                    return false;
                }
            });
            mMediaPlayer.prepare();
            mMediaPlayer.start();
        } catch (Exception e) {
            e.printStackTrace();
        }
    }

    /**
     * 停止播放音乐
     */
    private void stopPlay(){
        Log.i(TAG,"stopPlay");
        if(mMediaPlayer != null){
            mMediaPlayer.stop();
            mMediaPlayer.release();
            mMediaPlayer = null;
        }
    }

    /**
     * 取消设备配对
     */
    private void removeBond(BluetoothDevice device) {
        if (device != null) {
            try {
                Log.i(TAG,"unPairAllDevices:" + device.getName());
                Method removeBond = device.getClass().getDeclaredMethod("removeBond");
                removeBond.invoke(device);
            } catch (Exception e) {
                e.printStackTrace();
            }
        }
    }
    /**
     * 取消所有配对
     */
    private void removeAllBonds(){
        Log.i(TAG,"unPairAllDevices");
        for(BluetoothDevice device:mBluetoothAdapter.getBondedDevices()){
            removeBond(device);
        }
    }

    /**
     * 注意，在程序退出之前（OnDestroy），需要断开蓝牙相关的Service
     * 否则，程序会报异常：service leaks
     */
    private void disableAdapter(){
        Log.i(TAG,"disableAdapter");
        if(mBluetoothAdapter == null){
            return;
        }
        if(mBluetoothAdapter.isDiscovering()){
            mBluetoothAdapter.cancelDiscovery();
        }

        //关闭ProfileProxy，也就是断开service连接
        mBluetoothAdapter.closeProfileProxy(BluetoothProfile.A2DP,mBluetoothA2dp);
        if(mBluetoothAdapter.isEnabled()){
            boolean ret = mBluetoothAdapter.disable();
            Log.i(TAG,"disable adapter:"+ret);
        }
    }
}
